<template>
	<view class="avatar-cropper" v-if="show">
		<view class="cropper-container">
			<!-- 导航栏 -->
			<view class="cropper-header" :style="{paddingTop: headerPaddingTop + 'px'}">
				<view class="header-btn cancel-btn" @click="handleCancel">
					<text class="btn-text">{{ $t('avatarCropper.cancel') }}</text>
				</view>
				<text class="title" @longpress="debugCurrentState">{{ $t('avatarCropper.editAvatar') }}</text>
				<view class="header-btn confirm-btn" @click="handleConfirm">
					<text class="btn-text">{{ $t('avatarCropper.confirm') }}</text>
				</view>
			</view>

			<!-- 裁剪区域 -->
			<view class="cropper-content">
				<!-- 原图显示 -->
				<view class="image-container">
					<image
						:src="imagePath"
						class="source-image"
						mode="aspectFit"
						@load="onImageLoad"
						:style="{
							width: imageStyle.width + 'px',
							height: imageStyle.height + 'px',
							left: imageStyle.left + 'px',
							top: imageStyle.top + 'px',
							transform: 'scale(' + scale + ')'
						}"
						@touchstart="handleTouchStart"
						@touchmove="handleTouchMove"
						@touchend="handleTouchEnd"
					/>

					<!-- 裁剪遮罩 -->
					<view class="crop-mask">
						<view class="mask-top"></view>
						<view class="mask-middle">
							<view class="mask-left"></view>
							<view class="crop-circle">
								<view class="circle-border"></view>
								<view class="circle-guides">
									<view class="guide-line guide-horizontal"></view>
									<view class="guide-line guide-vertical"></view>
								</view>
							</view>
							<view class="mask-right"></view>
						</view>
						<view class="mask-bottom"></view>
					</view>
				</view>

				<!-- 缩放控制 -->
				<view class="scale-control">
					<view class="scale-icon">🔍</view>
					<slider
						class="scale-slider"
						:value="scalePercent"
						:min="50"
						:max="300"
						@change="handleScaleChange"
						@changing="handleScaleChanging"
						activeColor="#007AFF"
						backgroundColor="rgba(255,255,255,0.3)"
						block-size="20"
					/>
					<text class="scale-percent">{{scalePercent}}%</text>
				</view>
			</view>

			<!-- 预览区域 -->
			<view class="preview-section">
				<view class="preview-label">
					<text class="preview-title">{{ $t('avatarCropper.previewEffect') }}</text>
				</view>
				<view class="preview-wrapper">
					<view class="preview-container">
						<canvas
							canvas-id="previewCanvas"
							class="preview-canvas"
							:style="{width: previewSize + 'px', height: previewSize + 'px'}"
						></canvas>
						<view class="preview-ring"></view>
					</view>
				</view>
				<!-- 隐藏的裁剪canvas -->
				<canvas
					canvas-id="cropCanvas"
					:style="{width: maxSize + 'px', height: maxSize + 'px', position: 'absolute', left: '-9999px', top: '-9999px'}"
				></canvas>
			</view>
		</view>
	</view>
</template>

<script>
export default {
	props: {
		show: {
			type: Boolean,
			default: false
		},
		imagePath: {
			type: String,
			default: ''
		},
		// 压缩选项
		compress: {
			type: Boolean,
			default: true
		},
		quality: {
			type: Number,
			default: 0.8 // 默认压缩质量80%
		},
		maxSize: {
			type: Number,
			default: 800 // 最大尺寸800px
		}
	},
	data() {
		return {
			// 容器尺寸
			containerWidth: 375,
			containerHeight: 300,

			// 裁剪圆形尺寸
			cropSize: 200,

			// 预览尺寸
			previewSize: 80,

			// 状态栏高度
			statusBarHeight: 0,

			// 图片信息
			imageInfo: {
				width: 0,
				height: 0,
				naturalWidth: 0,
				naturalHeight: 0
			},

			// 图片样式
			imageStyle: {
				width: 0,
				height: 0,
				left: 0,
				top: 0
			},

			// 缩放比例
			scale: 1,
			scalePercent: 100,

			// 触摸相关
			touchData: {
				startX: 0,
				startY: 0,
				startLeft: 0,
				startTop: 0,
				touching: false
			}
		}
	},
	computed: {
		// 计算头部 padding-top，兼容不同设备
		headerPaddingTop() {
			// 优先使用系统状态栏高度
			return this.statusBarHeight + 12
		}
	},
	mounted() {
		this.initContainer()
	},
	watch: {
		imagePath(newVal) {
			if (newVal) {
				this.$nextTick(() => {
					this.initImage()
				})
			}
		},
		show(newVal) {
			if (newVal && this.imagePath) {
				this.$nextTick(() => {
					this.initImage()
				})
			}
		}
	},
	methods: {
		// 初始化容器
		initContainer() {
			const systemInfo = uni.getSystemInfoSync()
			this.containerWidth = systemInfo.windowWidth
			this.containerHeight = 400 // 增加高度给裁剪区域更多空间
			this.cropSize = Math.min(this.containerWidth - 60, 200)
			this.previewSize = 80
			// 获取状态栏高度
			this.statusBarHeight = systemInfo.statusBarHeight || 0
		},

		// 图片加载完成
		onImageLoad(e) {
			this.imageInfo.naturalWidth = e.detail.width
			this.imageInfo.naturalHeight = e.detail.height
			this.initImagePosition()
			this.updatePreview()
		},

		// 初始化图片
		initImage() {
			// 重置状态
			this.scale = 1
			this.scalePercent = 100
			this.imageStyle = {
				width: 0,
				height: 0,
				left: 0,
				top: 0
			}
		},

		// 初始化图片位置
		initImagePosition() {
			const { naturalWidth, naturalHeight } = this.imageInfo
			const aspectRatio = naturalWidth / naturalHeight

			let displayWidth, displayHeight

			// 根据长宽比计算显示尺寸
			if (aspectRatio > 1) {
				// 横图
				displayWidth = this.containerWidth
				displayHeight = displayWidth / aspectRatio
			} else {
				// 竖图
				displayHeight = this.containerHeight
				displayWidth = displayHeight * aspectRatio
			}

			// 确保图片能覆盖裁剪区域
			const minScale = Math.max(
				this.cropSize / displayWidth,
				this.cropSize / displayHeight
			)

			if (minScale > 1) {
				displayWidth *= minScale
				displayHeight *= minScale
			}

			this.imageStyle = {
				width: displayWidth,
				height: displayHeight,
				left: (this.containerWidth - displayWidth) / 2,
				top: (this.containerHeight - displayHeight) / 2
			}

			// 不要修改 imageInfo，它应该保存原始的naturalWidth和naturalHeight信息
		},

		// 触摸开始
		handleTouchStart(e) {
			const touch = e.touches[0]
			this.touchData = {
				startX: touch.clientX,
				startY: touch.clientY,
				startLeft: this.imageStyle.left,
				startTop: this.imageStyle.top,
				touching: true
			}
		},

		// 触摸移动
		handleTouchMove(e) {
			if (!this.touchData.touching) return

			e.preventDefault()
			const touch = e.touches[0]
			const deltaX = touch.clientX - this.touchData.startX
			const deltaY = touch.clientY - this.touchData.startY

			// 计算新的图片中心点位置
			const currentCenterX = this.touchData.startLeft + this.imageStyle.width / 2
			const currentCenterY = this.touchData.startTop + this.imageStyle.height / 2
			const newCenterX = currentCenterX + deltaX
			const newCenterY = currentCenterY + deltaY

			// 边界限制：确保缩放后的图片能完全覆盖裁剪圆形
			const cropCenterX = this.containerWidth / 2
			const cropCenterY = this.containerHeight / 2
			const cropRadius = this.cropSize / 2
			const scaledWidth = this.imageStyle.width * this.scale
			const scaledHeight = this.imageStyle.height * this.scale

			// 图片中心点的可移动范围
			const minCenterX = cropCenterX - scaledWidth / 2 + cropRadius
			const maxCenterX = cropCenterX + scaledWidth / 2 - cropRadius
			const minCenterY = cropCenterY - scaledHeight / 2 + cropRadius
			const maxCenterY = cropCenterY + scaledHeight / 2 - cropRadius

			// 限制中心点位置
			const limitedCenterX = Math.max(minCenterX, Math.min(maxCenterX, newCenterX))
			const limitedCenterY = Math.max(minCenterY, Math.min(maxCenterY, newCenterY))

			// 反推left/top位置
			this.imageStyle.left = limitedCenterX - this.imageStyle.width / 2
			this.imageStyle.top = limitedCenterY - this.imageStyle.height / 2

			this.updatePreview()
		},

		// 触摸结束
		handleTouchEnd() {
			this.touchData.touching = false
		},

		// 缩放变化（滑动结束）
		handleScaleChange(e) {
			this.scalePercent = e.detail.value
			this.scale = e.detail.value / 100
			this.updatePreview()
		},

		// 缩放变化（实时滑动）
		handleScaleChanging(e) {
			this.scalePercent = e.detail.value
			this.scale = e.detail.value / 100
			this.updatePreview()
		},

		// 计算裁剪参数（公共方法）
		calculateCropParams() {
			const cropCenterX = this.containerWidth / 2
			const cropCenterY = this.containerHeight / 2

			// CSS transform-origin: center 意味着从中心点缩放
			// 原始中心点位置（不受缩放影响）
			const originalCenterX = this.imageStyle.left + this.imageStyle.width / 2
			const originalCenterY = this.imageStyle.top + this.imageStyle.height / 2

			// 缩放后的实际尺寸
			const scaledWidth = this.imageStyle.width * this.scale
			const scaledHeight = this.imageStyle.height * this.scale

			// 缩放后的视觉位置（从中心向外扩展）
			const visualLeft = originalCenterX - scaledWidth / 2
			const visualTop = originalCenterY - scaledHeight / 2

			// 缩放后的视觉中心（与原始中心相同）
			const visualCenterX = originalCenterX
			const visualCenterY = originalCenterY

			// 裁剪偏移量
			const offsetX = visualCenterX - cropCenterX
			const offsetY = visualCenterY - cropCenterY

			return {
				cropCenterX,
				cropCenterY,
				scaledWidth,
				scaledHeight,
				visualLeft,
				visualTop,
				visualCenterX,
				visualCenterY,
				offsetX,
				offsetY,
				// 保留原始值用于调试
				originalCenterX,
				originalCenterY
			}
		},

		// 更新预览
		updatePreview() {
			this.$nextTick(() => {
				const ctx = uni.createCanvasContext('previewCanvas', this)

				// 清除画布
				ctx.clearRect(0, 0, this.previewSize, this.previewSize)

				// 设置圆形裁剪
				ctx.save()
				ctx.arc(this.previewSize / 2, this.previewSize / 2, this.previewSize / 2, 0, 2 * Math.PI)
				ctx.clip()

				// 使用公共计算方法
				const params = this.calculateCropParams()

				// 计算在预览canvas中的绘制参数
				const previewScale = this.previewSize / this.cropSize

				// 裁剪框中可见的图片部分在预览中的位置
				// 图片在裁剪框中的相对位置
				const relativeX = params.visualLeft - (params.cropCenterX - this.cropSize / 2)
				const relativeY = params.visualTop - (params.cropCenterY - this.cropSize / 2)

				// 缩放到预览尺寸
				const previewX = relativeX * previewScale
				const previewY = relativeY * previewScale
				const previewWidth = params.scaledWidth * previewScale
				const previewHeight = params.scaledHeight * previewScale

				console.log('预览参数:', {
					...params,
					scale: this.scale,
					previewScale: previewScale,
					relativePosition: { x: relativeX, y: relativeY },
					previewPosition: { x: previewX, y: previewY },
					previewSize: { width: previewWidth, height: previewHeight }
				})

				// 绘制图片
				ctx.drawImage(
					this.imagePath,
					previewX,
					previewY,
					previewWidth,
					previewHeight
				)

				ctx.restore()
				ctx.draw()
			})
		},

		// 获取裁剪后的图片数据
		getCroppedImage() {
			return new Promise((resolve) => {
				// 使用独立的裁剪canvas
				const ctx = uni.createCanvasContext('cropCanvas', this)

				// 根据压缩设置确定输出尺寸
				let outputSize = 200
				if (this.compress && this.maxSize) {
					outputSize = Math.min(outputSize, this.maxSize)
				}

				ctx.clearRect(0, 0, outputSize, outputSize)
				ctx.save()
				ctx.arc(outputSize / 2, outputSize / 2, outputSize / 2, 0, 2 * Math.PI)
				ctx.clip()

				// 使用与预览完全相同的计算逻辑
				const params = this.calculateCropParams()

				// 计算在输出canvas中的绘制参数
				const outputScale = outputSize / this.cropSize

				// 裁剪框中可见的图片部分在输出中的位置
				// 图片在裁剪框中的相对位置
				const relativeX = params.visualLeft - (params.cropCenterX - this.cropSize / 2)
				const relativeY = params.visualTop - (params.cropCenterY - this.cropSize / 2)

				// 缩放到输出尺寸
				const outputX = relativeX * outputScale
				const outputY = relativeY * outputScale
				const outputWidth = params.scaledWidth * outputScale
				const outputHeight = params.scaledHeight * outputScale

				console.log('裁剪参数:', {
					...params,
					scale: this.scale,
					outputScale: outputScale,
					relativePosition: { x: relativeX, y: relativeY },
					outputPosition: { x: outputX, y: outputY },
					outputSize: { width: outputWidth, height: outputHeight }
				})

				ctx.drawImage(
					this.imagePath,
					outputX,
					outputY,
					outputWidth,
					outputHeight
				)

				ctx.restore()
				ctx.draw(true, () => {
					// 导出图片，支持压缩
					uni.canvasToTempFilePath({
						canvasId: 'cropCanvas',
						width: outputSize,
						height: outputSize,
						destWidth: outputSize,
						destHeight: outputSize,
						fileType: 'jpg', // 使用jpg格式支持压缩
						quality: this.compress ? this.quality : 1,
						success: async (res) => {
							console.log('裁剪成功:', res.tempFilePath)

							// 如果启用压缩，进一步压缩处理
							if (this.compress) {
								const compressedPath = await this.compressImage(res.tempFilePath)
								resolve(compressedPath)
							} else {
								resolve(res.tempFilePath)
							}
						},
						fail: (err) => {
							console.error('裁剪失败:', err)
							resolve(null)
						}
					}, this)
				})
			})
		},

		// 压缩图片
		compressImage(imagePath) {
			return new Promise((resolve) => {
				// 获取图片信息
				uni.getImageInfo({
					src: imagePath,
					success: (info) => {
						console.log('原始图片信息:', {
							width: info.width,
							height: info.height,
							path: info.path,
							size: info.size || '未知'
						})

						// 使用uni.compressImage API进行压缩
						uni.compressImage({
							src: imagePath,
							quality: this.quality * 100, // uni.compressImage的quality是0-100
							success: (res) => {
								console.log('压缩后路径:', res.tempFilePath)

								// 获取压缩后的图片信息
								uni.getImageInfo({
									src: res.tempFilePath,
									success: (compressedInfo) => {
										console.log('压缩后图片信息:', {
											width: compressedInfo.width,
											height: compressedInfo.height,
											path: compressedInfo.path,
											size: compressedInfo.size || '未知'
										})

										// 如果有文件大小信息，计算压缩率
										if (info.size && compressedInfo.size) {
											const compressionRate = (1 - compressedInfo.size / info.size) * 100
											console.log(`压缩率: ${compressionRate.toFixed(1)}%`)
											console.log(`原始大小: ${(info.size / 1024).toFixed(1)}KB`)
											console.log(`压缩后大小: ${(compressedInfo.size / 1024).toFixed(1)}KB`)
										}
									}
								})

								resolve(res.tempFilePath)
							},
							fail: (err) => {
								console.error('压缩失败:', err)
								// 压缩失败则返回原图
								resolve(imagePath)
							}
						})
					},
					fail: () => {
						// 获取信息失败则返回原图
						resolve(imagePath)
					}
				})
			})
		},

		// 确认裁剪
		async handleConfirm() {
			// 显示处理中
			uni.showLoading({
				title: '处理中...',
				mask: true
			})

			try {
				const croppedImage = await this.getCroppedImage()
				uni.hideLoading()

				if (croppedImage) {
					// 获取最终图片信息
					uni.getImageInfo({
						src: croppedImage,
						success: (info) => {
							const fileSize = info.size || 0
							if (fileSize > 0) {
								console.log(`最终图片大小: ${(fileSize / 1024).toFixed(1)}KB`)
								uni.showToast({
									title: `已压缩至 ${(fileSize / 1024).toFixed(0)}KB`,
									icon: 'none',
									duration: 1500
								})
							}
						}
					})

					setTimeout(() => {
						this.$emit('confirm', croppedImage)
					}, 500)
				}
			} catch (error) {
				uni.hideLoading()
				uni.showToast({
					title: '处理失败',
					icon: 'none'
				})
			}
		},

		// 取消裁剪
		handleCancel() {
			this.$emit('cancel')
		},

		// 调试方法：打印当前状态
		debugCurrentState() {
			const params = this.calculateCropParams()
			console.log('=== 当前裁剪状态 ===')
			console.log('容器尺寸:', { width: this.containerWidth, height: this.containerHeight })
			console.log('裁剪圆形:', {
				size: this.cropSize,
				centerX: params.cropCenterX,
				centerY: params.cropCenterY,
				left: params.cropCenterX - this.cropSize / 2,
				top: params.cropCenterY - this.cropSize / 2
			})
			console.log('图片样式 (CSS):', this.imageStyle)
			console.log('缩放比例:', this.scale)
			console.log('视觉位置 (缩放后):', {
				left: params.visualLeft,
				top: params.visualTop,
				width: params.scaledWidth,
				height: params.scaledHeight,
				centerX: params.visualCenterX,
				centerY: params.visualCenterY
			})
			console.log('相对位置 (相对于裁剪框):', {
				x: params.visualLeft - (params.cropCenterX - this.cropSize / 2),
				y: params.visualTop - (params.cropCenterY - this.cropSize / 2)
			})
			console.log('===================')
		}
	}
}
</script>

<style lang="scss" scoped>
.avatar-cropper {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	background: linear-gradient(135deg, #1a1a1a, #000000);
	z-index: 9999;
	animation: fadeIn 0.3s ease;

	.cropper-container {
		width: 100%;
		height: 100%;
		display: flex;
		flex-direction: column;
	}

	.cropper-header {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 12px 20px;
		background: linear-gradient(180deg, rgba(0, 0, 0, 0.9), rgba(0, 0, 0, 0.7));
		backdrop-filter: blur(10px);
		border-bottom: 1px solid rgba(255, 255, 255, 0.1);

		.header-btn {
			padding: 8px 16px;
			border-radius: 20px;
			transition: all 0.2s ease;
			background: rgba(255, 255, 255, 0.1);
			backdrop-filter: blur(10px);

			.btn-text {
				font-size: 16px;
				font-weight: 500;
			}

			&.cancel-btn {
				.btn-text {
					color: #FF6B6B;
				}

				&:active {
					background: rgba(255, 107, 107, 0.2);
					transform: scale(0.95);
				}
			}

			&.confirm-btn {
				background: linear-gradient(135deg, #007AFF, #0056D3);

				.btn-text {
					color: #FFFFFF;
				}

				&:active {
					background: linear-gradient(135deg, #0056D3, #003AA3);
					transform: scale(0.95);
				}
			}
		}

		.title {
			color: #FFFFFF;
			font-size: 18px;
			font-weight: 600;
			text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
		}
	}

	.cropper-content {
		flex: 1;
		position: relative;
		overflow: hidden;

		.image-container {
			position: relative;
			width: 100%;
			height: 400px;

			.source-image {
				position: absolute;
				transform-origin: center;
				transition: transform 0.1s ease;
			}

			.crop-mask {
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				pointer-events: none;

				.mask-top, .mask-bottom {
					width: 100%;
					background-color: rgba(0, 0, 0, 0.6);
				}

				.mask-top {
					height: 100px; // 增加上方遮罩高度，让圆形居中
				}

				.mask-bottom {
					height: 100px; // 增加下方遮罩高度，让圆形居中
				}

				.mask-middle {
					display: flex;
					height: 200px;

					.mask-left, .mask-right {
						background-color: rgba(0, 0, 0, 0.6);
						flex: 1;
					}

					.crop-circle {
						width: 200px;
						height: 200px;
						position: relative;

						.circle-border {
							position: absolute;
							top: 0;
							left: 0;
							width: 100%;
							height: 100%;
							border: 3px solid #007AFF;
							border-radius: 50%;
							box-sizing: border-box;
							box-shadow:
								0 0 0 1px rgba(255, 255, 255, 0.3),
								0 0 20px rgba(0, 122, 255, 0.3),
								inset 0 0 20px rgba(0, 122, 255, 0.1);
						}

						.circle-guides {
							position: absolute;
							top: 50%;
							left: 50%;
							transform: translate(-50%, -50%);
							width: 80%;
							height: 80%;

							.guide-line {
								position: absolute;
								background-color: rgba(255, 255, 255, 0.4);

								&.guide-horizontal {
									top: 50%;
									left: 0;
									width: 100%;
									height: 1px;
									transform: translateY(-50%);
								}

								&.guide-vertical {
									top: 0;
									left: 50%;
									width: 1px;
									height: 100%;
									transform: translateX(-50%);
								}
							}
						}
					}
				}
			}
		}

		.scale-control {
			position: absolute;
			bottom: 30px;
			left: 20px;
			right: 20px;
			display: flex;
			align-items: center;
			padding: 15px 20px;
			background: rgba(0, 0, 0, 0.7);
			backdrop-filter: blur(15px);
			border-radius: 25px;
			border: 1px solid rgba(255, 255, 255, 0.1);
			box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);

			.scale-icon {
				font-size: 18px;
				margin-right: 15px;
				filter: grayscale(1) brightness(2);
			}

			.scale-slider {
				flex: 1;
				margin: 0 15px;
			}

			.scale-percent {
				color: #FFFFFF;
				font-size: 14px;
				font-weight: 600;
				min-width: 45px;
				text-align: center;
				background: rgba(0, 122, 255, 0.2);
				padding: 4px 8px;
				border-radius: 12px;
				border: 1px solid rgba(0, 122, 255, 0.3);
			}
		}
	}

	.preview-section {
		padding: 20px;
		background: linear-gradient(180deg, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.9));
		backdrop-filter: blur(15px);
		border-top: 1px solid rgba(255, 255, 255, 0.1);

		.preview-label {
			display: flex;
			justify-content: center;
			margin-bottom: 15px;

			.preview-title {
				color: #FFFFFF;
				font-size: 14px;
				font-weight: 500;
				opacity: 0.8;
				text-transform: uppercase;
				letter-spacing: 1px;
			}
		}

		.preview-wrapper {
			display: flex;
			justify-content: center;

			.preview-container {
				position: relative;

				.preview-canvas {
					border-radius: 50%;
					box-shadow:
						0 0 0 3px rgba(0, 122, 255, 0.5),
						0 0 0 6px rgba(255, 255, 255, 0.1),
						0 8px 32px rgba(0, 0, 0, 0.5);
				}

				.preview-ring {
					position: absolute;
					top: -6px;
					left: -6px;
					right: -6px;
					bottom: -6px;
					border: 2px solid transparent;
					border-radius: 50%;
					background: linear-gradient(135deg, #007AFF, #00D4FF, #007AFF);
					background-size: 200% 200%;
					animation: rotateGradient 3s linear infinite;
					z-index: -1;
				}
			}
		}
	}
}

@keyframes fadeIn {
	from {
		opacity: 0;
		transform: translateY(20px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

@keyframes pulse {
	0%, 100% {
		opacity: 1;
		transform: scale(1);
	}
	50% {
		opacity: 0.8;
		transform: scale(1.02);
	}
}

@keyframes rotateGradient {
	0% {
		background-position: 0% 50%;
	}
	50% {
		background-position: 100% 50%;
	}
	100% {
		background-position: 0% 50%;
	}
}
</style>